package com.leviassaf.al_app_one;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.facebook.Request;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphObject;
import com.facebook.model.GraphPlace;
import com.facebook.model.GraphUser;
import com.facebook.widget.ProfilePictureView;

public class SelectionFragment extends Fragment {

	private ListView listView;
	private List<BaseListElement> listElements;

	private static final String TAG = "SelectionFragment";
	private ProfilePictureView profilePictureView;
	private TextView txtvwUserName;
	private static final int REAUTH_ACTIVITY_CODE = 100;

	UiLifecycleHelper uiLifecycleHelper;
	private Session.StatusCallback statusCallback = new Session.StatusCallback() {

		@Override
		public void call(Session session, SessionState state,
				Exception exception) {
			// TODO Auto-generated method stub
			onSessionStateChange(session, state, exception);
		}
	};

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreateView(inflater, container, savedInstanceState);
		View view = inflater.inflate(R.layout.selection, container, false);

		profilePictureView = (ProfilePictureView) view
				.findViewById(R.id.profilePictureView);
		profilePictureView.setCropped(true);
		txtvwUserName = (TextView) view.findViewById(R.id.txtvwUserName);

		listView = (ListView) view.findViewById(R.id.lstvw);
		listElements = new ArrayList<BaseListElement>();
		listElements.add(new PeopleListElement(0));
		listElements.add(new LocationListElement(1));
		
		if (savedInstanceState != null){
			for (BaseListElement baseListElement : listElements){
				baseListElement.restoreState(savedInstanceState);
			}
		}
		
		listView.setAdapter(new ActionListAdapter(getActivity(), R.id.lstvw,
				listElements));

		Session session = Session.getActiveSession();
		if (session != null && session.isOpened()) {
			makeMeRequest(session);
		}

		return view;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		uiLifecycleHelper = new UiLifecycleHelper(getActivity(), statusCallback);
		uiLifecycleHelper.onCreate(savedInstanceState);
	}

	private void makeMeRequest(final Session session) {
		Request request = Request.newMeRequest(session,
				new Request.GraphUserCallback() {

					@Override
					public void onCompleted(GraphUser user, Response response) {
						// TODO Auto-generated method stub
						if (session == Session.getActiveSession()) {
							if (user != null) {
								profilePictureView.setProfileId(user.getId());
								txtvwUserName.setText(user.getName());
							}
						}
						if (response.getError() != null) {
							// Handle errors
						}
					}
				});
		request.executeAsync();
	}

	private void onSessionStateChange(final Session session,
			SessionState sessionState, Exception exception) {
		if (session != null && session.isOpened()) {
			makeMeRequest(session);
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == REAUTH_ACTIVITY_CODE) {
			uiLifecycleHelper.onActivityResult(requestCode, resultCode, data);
		} else if (resultCode == Activity.RESULT_OK && requestCode >= 0 && requestCode < listElements.size()) {
			listElements.get(requestCode).onActivityResult(data);
		}
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		uiLifecycleHelper.onDestroy();
	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		uiLifecycleHelper.onPause();
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		uiLifecycleHelper.onResume();
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);
		for (BaseListElement baseListElement : listElements){
			baseListElement.onSaveInstanceState(outState);
		}
		uiLifecycleHelper.onSaveInstanceState(outState);
	}

	private class ActionListAdapter extends ArrayAdapter<BaseListElement> {
		private List<BaseListElement> listElements;

		public ActionListAdapter(Context context, int resource,
				List<BaseListElement> listElements) {
			super(context, resource, listElements);
			// TODO Auto-generated constructor stub
			this.listElements = listElements;
			for (int i = 0; i < listElements.size(); i++) {
				listElements.get(i).setAdapter(this);
			}
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			View view = convertView;
			if (view == null) {
				LayoutInflater layoutInflater = (LayoutInflater) getActivity()
						.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				view = layoutInflater.inflate(R.layout.listitem, null);
			}

			BaseListElement baseListElement = listElements.get(position);
			if (baseListElement != null) {
				view.setOnClickListener(baseListElement.getOnClickListener());
				ImageView imgvwIcon = (ImageView) view
						.findViewById(R.id.imgvwIcon);
				TextView txtvw1 = (TextView) view.findViewById(R.id.txtvw1);
				TextView txtvw2 = (TextView) view.findViewById(R.id.txtvw2);
				if (imgvwIcon != null) {
					imgvwIcon.setImageDrawable(baseListElement.getIcon());
				}
				if (txtvw1 != null) {
					txtvw1.setText(baseListElement.getText1());
				}
				if (txtvw2 != null) {
					txtvw2.setText(baseListElement.getText2());
				}
			}
			return view;
		}

	}

	private class PeopleListElement extends BaseListElement {

		private List<GraphUser> selectedUsers;
		private static final String FRIENDS_KEY = "friends";
		
		public PeopleListElement(int requestCode) {
			super(getActivity().getResources().getDrawable(
					R.drawable.action_people), getActivity().getResources()
					.getString(R.string.action_people), getActivity()
					.getResources().getString(R.string.action_people_default),
					requestCode);
			// TODO Auto-generated constructor stub
		}

		private void setUsersText() {
			String strText = null;
			if (selectedUsers != null) {
				if (selectedUsers.size() == 1) {
					strText = String.format(
							getResources().getString(
									R.string.single_user_selected),
							selectedUsers.get(0).getName());
				} else if (selectedUsers.size() == 2) {
					strText = String.format(
							getResources().getString(
									R.string.two_users_selected), selectedUsers
									.get(0).getName(), selectedUsers.get(1)
									.getName());
				} else if (selectedUsers.size() > 2) {
					strText = String.format(
							getResources().getString(
									R.string.multiple_users_selected),
							selectedUsers.get(0).getName(),
							(selectedUsers.size() - 1));
				}
			}
			if (strText == null) {
				strText = getResources().getString(
						R.string.action_people_default);
			}
			setText2(strText);
		}

		
		@Override
		protected void onActivityResult(Intent data) {
			// TODO Auto-generated method stub
			selectedUsers = ((ScrumptiousApplication) getActivity().getApplication()).getSelectedUsers();
			setUsersText();
			notifyDataChanged();
		}
		
		private byte[] getByteArray(List<GraphUser> users){
			List<String> usersAsString = new ArrayList<String>(users.size());
			for (GraphUser graphUser: users){
				usersAsString.add(graphUser.getInnerJSONObject().toString());
			}
			try{
				ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
				new ObjectOutputStream(byteArrayOutputStream).writeObject(usersAsString);
				return byteArrayOutputStream.toByteArray();
			}
			catch (IOException e){
				Log.e(TAG, "Unable to serialize users.", e);
			}
			return null;
		}

		@Override
		protected void onSaveInstanceState(Bundle bundle) {
			// TODO Auto-generated method stub
			if (selectedUsers != null){
				bundle.putByteArray(FRIENDS_KEY, getByteArray(selectedUsers));
			}
		}
		
		private List<GraphUser> restoreByteArray(byte[] bytes){
			try{
				List<String> usersAsString = (List<String>) (new ObjectInputStream(new ByteArrayInputStream(bytes))).readObject();
				if (usersAsString != null){
					List<GraphUser> users = new ArrayList<GraphUser>(usersAsString.size());
					for (String user : usersAsString){
						GraphUser graphUser = GraphObject.Factory.create(new JSONObject(user), GraphUser.class);
						users.add(graphUser);
					}
					return users;
				}
			}
			catch (ClassNotFoundException e){
				Log.e(TAG, "Unable to deserialize users.", e);				
			}
			catch (IOException e){
				Log.e(TAG, "Unable to deserialize users.", e);
			}
			catch (JSONException e){
				Log.e(TAG, "Unable to deserialize users.", e);
			}
			return null;
		}

		@Override
		protected boolean restoreState(Bundle savedState) {
			// TODO Auto-generated method stub
			byte[] bytes = savedState.getByteArray(FRIENDS_KEY);
			if (bytes != null){
				selectedUsers = restoreByteArray(bytes);
				setUsersText();
				return true;
			}
			return false;
		}

		@Override
		protected OnClickListener getOnClickListener() {
			// TODO Auto-generated method stub
			return new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					startPickerActivity(PickerActivity.FRIEND_PICKER,
							getRequestCode());
				}
			};
		}
	}

	private void startPickerActivity(Uri uriData, int intRequestCode) {
		Intent intent = new Intent();
		intent.setData(uriData);
		intent.setClass(getActivity(), PickerActivity.class);
		startActivityForResult(intent, intRequestCode);
	}
	
	private class LocationListElement extends BaseListElement{
		
		private static final String KEY_PLACE = "place";

		private GraphPlace graphPlaceSelected = null;
		
		private void setPlaceText(){
			String strText = null;
			if (graphPlaceSelected != null){
				strText = graphPlaceSelected.getName();
			}
			if (strText == null){
				strText = getResources().getString(R.string.action_location_default);
			}
			setText2(strText);
		}
		
		public LocationListElement(int requestCode) {
			super(
				getActivity().getResources().getDrawable(R.drawable.action_location), 
				getActivity().getResources().getString(R.string.action_location), 
				getActivity().getResources().getString(R.string.action_location_default), 
				requestCode
			);
			// TODO Auto-generated constructor stub
		}

		@Override
		protected void onActivityResult(Intent data) {
			// TODO Auto-generated method stub
			graphPlaceSelected = ((ScrumptiousApplication) getActivity().getApplication()).getSelectedPlace();
			setPlaceText();
			notifyDataChanged();
		}

		@Override
		protected OnClickListener getOnClickListener() {
			// TODO Auto-generated method stub
			return new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					startPickerActivity(PickerActivity.PLACE_PICKER, getRequestCode());
				}
			};
		}

		@Override
		protected void onSaveInstanceState(Bundle bundle) {
			// TODO Auto-generated method stub
			if (graphPlaceSelected != null){
				bundle.putString(KEY_PLACE, graphPlaceSelected.getInnerJSONObject().toString());
			}
		}

		@Override
		protected boolean restoreState(Bundle savedState) {
			// TODO Auto-generated method stub
			String strPlace = savedState.getString(KEY_PLACE);
			if (strPlace != null){
				try{
					graphPlaceSelected = GraphObject.Factory.create(new JSONObject(strPlace), GraphPlace.class);
					setPlaceText();return true;
				}
				catch (JSONException e){
					Log.e(TAG, "Unable to deseialize place.", e);
				}
			}
			return false;
		}
		
	}
}
